package com.wzcl.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.wzcl.app.dao.model.Activity;
import com.wzcl.app.dao.model.AppUser;
import com.wzcl.app.dao.model.UserGroup;
import com.wzcl.app.dao.repository.UserGroupRepository;
import com.wzcl.app.model.common.BusinessException;
import com.wzcl.app.model.common.CodeMsg;
import com.wzcl.app.model.common.MyPage;
import com.wzcl.app.model.dto.UserDto;
import com.wzcl.app.model.dto.UserGroupDto;
import com.wzcl.app.service.ActivityRuleService;
import com.wzcl.app.service.UserGroupService;
import com.wzcl.app.service.UserService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

@Log4j2
@Service
public class UserGroupServiceImpl implements UserGroupService {

    @Autowired
    private UserGroupRepository repository;

    @Autowired
    private UserService userService;

    @Autowired
    private ActivityRuleService ruleService;

    @Override
    public UserGroup addUserGroup(UserGroupDto userGroupDto) {
        UserGroup userGroup = new UserGroup();
        List<AppUser> users = null;
        if(userGroupDto.getIsGenerate()){
            UserDto userDto = new UserDto();
            userDto.setRealName(userGroupDto.getRealName());
            userDto.setPhone(userGroupDto.getPhone());
            userDto.setUserState(userGroupDto.getUserState());
            userDto.setType(userGroupDto.getType());
            userGroup.setConditions(JSON.toJSONString(userDto));
            users = userService.getUserList(userDto);
        }else {
            if (userGroupDto.getUserIds() == null || userGroupDto.getUserIds().size()==0){
                throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL,"缺少用户信息");
            }
            users = userService.getUserById(userGroupDto.getUserIds());
        }
        userGroup.setName(userGroupDto.getName());
        userGroup.setIsGenerate(userGroupDto.getIsGenerate());
        userGroup.setTag(StringUtils.join(userGroupDto.getTag(),","));
        userGroup.setUserList(users);
        return repository.save(userGroup);
    }

    @Override
    public UserGroup delUserGroupById(Integer id) {
        //校验获取
        UserGroup userGroup = getAndCheckById(id);
        //删除前先校验能否删除
        Long count = ruleService.countByGroupId(id);
        if(count>0){
            throw new BusinessException(CodeMsg.USER_GROUP_OPERATE_FAIL,"请先删除相关活动规则");
        }
        log.info("UserGroup:{} Physical deletion", JSON.toJSONString(userGroup));
        repository.delete(userGroup);
        return userGroup;
    }

    @Override
    public UserGroup refreshUserGroup(Integer id) {
        //检查获取
        UserGroup userGroup = getAndCheckById(id);
        //刷新用户组
        if(userGroup.getIsGenerate()){
            UserDto userDto = JSON.parseObject(userGroup.getConditions(), UserDto.class);
            List<AppUser> userList = userService.getUserList(userDto);
            userGroup.setUserList(userList);
            log.info("UserGroup ID:{} has refreshed",userGroup.getId());
            return repository.save(userGroup);
        }
        throw new BusinessException(CodeMsg.USER_GROUP_OPERATE_FAIL,"自定义用户组无法刷新");
    }

    @Override
    public UserGroup updateUserGroup(UserGroupDto userGroupDto) {
        UserGroup userGroup = getAndCheckById(userGroupDto);
        //校验通过
        List<AppUser> users = null;
        if(userGroupDto.getIsGenerate()){
            UserDto userDto = new UserDto();
            userDto.setRealName(userGroupDto.getRealName());
            userDto.setPhone(userGroupDto.getPhone());
            userDto.setUserState(userGroupDto.getUserState());
            userDto.setType(userGroupDto.getType());
            userGroup.setConditions(JSON.toJSONString(userDto));
            users = userService.getUserList(userDto);
        }else {
            if (userGroupDto.getUserIds() == null || userGroupDto.getUserIds().size()==0){
                throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL,"缺少用户信息");
            }
            users = userService.getUserById(userGroupDto.getUserIds());
        }
        userGroup.setName(userGroupDto.getName());
        userGroup.setIsGenerate(userGroupDto.getIsGenerate());
        userGroup.setTag(StringUtils.join(userGroupDto.getTag(),","));
        userGroup.setUserList(users);
        return repository.save(userGroup);
    }

    @Override
    public UserGroup getUserGroupById(Integer id) {
        Optional<UserGroup> optional = repository.findById(id);
        return optional.orElse(null);
    }


    @Override
    public UserGroup getAndCheckById(Integer id) {
        if (id == null) {
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少用户组Id");
        }
        UserGroup userGroup = getUserGroupById(id);
        if(userGroup == null){
            throw new BusinessException(CodeMsg.USER_GROUP_NOT_EXIST);
        }
        return userGroup;
    }

    @Override
    public List<UserGroup> getUserGroupList(UserGroupDto userGroupDto) {
        return repository.findAll(getSpecification(userGroupDto),userGroupDto.getSort());
    }

    @Override
    public MyPage<UserGroup> getUserGroupPage(UserGroupDto userGroupDto) {
        Page<UserGroup> all = repository.findAll(getSpecification(userGroupDto), userGroupDto.getPageable());
        ArrayList<UserGroup> list = new ArrayList<>(all.getContent());
        Collections.reverse(list);
        MyPage<UserGroup> myPage = new MyPage<>();
        myPage.setContent(list);
        myPage.setTotalElements(all.getTotalElements());
        return myPage;
    }


    private Specification<UserGroup> getSpecification(UserGroupDto userGroupDto) {
        return new Specification<UserGroup>() {
            @Override
            public Predicate toPredicate(Root<UserGroup> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<Predicate>();
                if(userGroupDto.getIsGenerate() != null){
                    predicates.add(criteriaBuilder.equal(root.get("isGenerate"),userGroupDto.getIsGenerate()));
                }
                if(StringUtils.isNotBlank(userGroupDto.getName())){
                    predicates.add(criteriaBuilder.like(root.get("name"),"%"+userGroupDto.getName()+"%"));
                }
                if(userGroupDto.getTag() != null && userGroupDto.getTag().size()>0){
                    for (String tagStr : userGroupDto.getTag()) {
                        predicates.add(criteriaBuilder.like(root.get("tag"),"%"+tagStr+"%"));
                    }
                }
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
    }
}
